package cn.yto.print.service.impl;

import cn.hutool.json.JSONUtil;
import cn.yto.print.config.CaffeineCacheConfig;
import cn.yto.print.config.PrintFutureContext;
import cn.yto.print.enums.PluginRegistryEnum;
import cn.yto.print.enums.PrintCmdEnum;
import cn.yto.print.enums.ResponseCodeEnum;
import cn.yto.print.model.dto.PrintCacheDTO;
import cn.yto.print.model.request.AiKuCunPrintRequest;
import cn.yto.print.model.request.PrintTaskRequest;
import cn.yto.print.model.response.AiKuCunPrintResponse;
import cn.yto.print.model.response.PrintTaskResponse;
import cn.yto.print.plugins.SocketSessionContext;
import cn.yto.print.service.PrintConsumerService;
import cn.yto.print.service.handle.ITextMessageFunction;
import cn.yto.print.service.handle.MessageHandler;
import cn.yto.print.utils.AkcSignatureUtil;
import cn.yto.print.utils.PrintTaskUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;

@Slf4j
@Component
public class AiKuCunMessageHandler extends MessageHandler {

    private SocketSessionContext socketSessionContext;

    @Override
    public void initialize() {
        socketSessionContext = new SocketSessionContext(PluginRegistryEnum.AKC, createMessageHandler());
    }

    @Override
    public ITextMessageFunction createMessageHandler() {
        return (session, message) -> {
            CaffeineCacheConfig.getHeartCache().put(PluginRegistryEnum.AKC.getCode(), 0);
            AiKuCunPrintResponse ackPrintResponse;
            try {
                ackPrintResponse = JSONUtil.toBean(message.getPayload(), AiKuCunPrintResponse.class);
            } catch (Exception e) {
                log.error("爱库存打印组件回执报文解析异常，报文将丢弃~", e);
                return;
            }

            if (null != ackPrintResponse.getLocals() && !StringUtils.isEmpty(ackPrintResponse.getLocals().getLocalVersion())) {
                return;
            }
            if ("00000".equals(ackPrintResponse.getCode())) {
                return;
            }
            if (StringUtils.isEmpty(ackPrintResponse.getPushBackMessage().getTaskId())) {
                return;
            }
            PrintCacheDTO printCache = CaffeineCacheConfig.getPrintCache().getIfPresent(ackPrintResponse.getPushBackMessage().getTaskId());
            if (null == printCache) {
                log.error("爱库存打印任务 TaskID：{} 缓存不存在，报文将丢弃~", ackPrintResponse.getPushBackMessage().getTaskId());
                return;
            }

            PrintTaskResponse.PrintStatus printStatus = new PrintTaskResponse.PrintStatus();
            printStatus.setStatus("200".equals(ackPrintResponse.getCode()) ? ResponseCodeEnum.SUCCESS.getStatus() : ResponseCodeEnum.FAILURE.getStatus());
            printStatus.setDocumentID(ackPrintResponse.getPushBackMessage().getRequestId());
            printStatus.setMsg(ackPrintResponse.getMessage());
            List<PrintTaskResponse.PrintStatus> printStatusCache = CollectionUtils.isEmpty(printCache.getPrintStatus()) ? Lists.newArrayList() : printCache.getPrintStatus();
            printStatusCache.add(printStatus);
            printCache.setPrintStatus(printStatusCache);
            List<String> documentIds = printCache.getDocumentIds();
            if (1 == documentIds.size() && documentIds.get(0).equals(ackPrintResponse.getPushBackMessage().getRequestId())) {
                PrintTaskResponse printTaskResponse = new PrintTaskResponse();
                printTaskResponse.setCmd(PrintCmdEnum.NOTIFY_PRINT_RESULT.getCmd());
                printTaskResponse.setTaskId(ackPrintResponse.getPushBackMessage().getTaskId());
                printTaskResponse.setSessionId(printCache.getSessionId());
                printTaskResponse.setTemplateType(printCache.getTemplateType());
                printTaskResponse.setPrintStatus(printCache.getPrintStatus());
                CompletableFuture<PrintTaskResponse> future = PrintFutureContext.getResponseFuture(ackPrintResponse.getPushBackMessage().getTaskId());
                if (null != future) {
                    future.complete(printTaskResponse);
                } else {
                    PrintConsumerService.handleTimeOutResponse(printTaskResponse);
                }
                CaffeineCacheConfig.getPrintCache().invalidate(ackPrintResponse.getPushBackMessage().getTaskId());
            } else {
                documentIds.remove(ackPrintResponse.getPushBackMessage().getRequestId());
                printCache.setDocumentIds(documentIds);
                CaffeineCacheConfig.getPrintCache().put(ackPrintResponse.getPushBackMessage().getTaskId(), printCache);
            }
        };
    }

    @Override
    public List<AiKuCunPrintRequest> buildPrintRequest(PrintTaskRequest printTaskRequest) {
        List<AiKuCunPrintRequest> ackRequestList = new ArrayList<>();
        printTaskRequest.getDocuments().forEach(doc -> {
            AiKuCunPrintRequest aiKuCunTask = new AiKuCunPrintRequest();
            aiKuCunTask.setEsubrc("SendPdfToPrint");
            aiKuCunTask.setLogisticsNo(doc.getWaybillCode());
            aiKuCunTask.setRequestId(doc.getDocumentID());
            aiKuCunTask.setTaskId(printTaskRequest.getTaskId());
            aiKuCunTask.setPrintName(printTaskRequest.getPrinter());
            aiKuCunTask.setMxEctData(doc.getPrintData());
            aiKuCunTask.setTemplateUrl(doc.getTemplateUrl());
            aiKuCunTask.setCustomData(Lists.newArrayList(doc.getCustomData()));
            if (!CollectionUtils.isEmpty(doc.getAddData())) {
                aiKuCunTask.setSenderInfo(Lists.newArrayList(doc.getAddData()));
            }
            String params = AkcSignatureUtil.generateSignature(JSONUtil.toJsonStr(aiKuCunTask), doc.getParams());
            aiKuCunTask.setParams(params);
            ackRequestList.add(aiKuCunTask);
        });
        return ackRequestList;
    }

    @Override
    public CompletableFuture<PrintTaskResponse> processMessage(PrintTaskRequest printParam) {
        List<AiKuCunPrintRequest> aiKuCunPrintRequest = buildPrintRequest(printParam);
        aiKuCunPrintRequest.forEach(request -> socketSessionContext.sendPrintRequest(request));
        PrintTaskUtil.addPrintTaskCache(printParam);
        CompletableFuture<PrintTaskResponse> completableFuture = new CompletableFuture<>();
        PrintFutureContext.addResponseFuture(printParam.getTaskId(), completableFuture);
        return completableFuture;
    }

    @Override
    public SocketSessionContext getSocketContext() {
        return socketSessionContext;
    }

}
